<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<script>
    let target = null
    function Vue({data}){
        this._data = data

        for (let key in this._data){
            Object.defineProperty(this,key,{
                get(){
                    return this._data[key]
                },
                set(v) {
                    this._data[key] = v
                }
            })
        }
        observe(this._data)
    }
    function observe(data){
        if(typeof data !== "object" || data === null) return

        new Observe(data)
    }
    class Observe{
        constructor(data) {
            this.data = data
            if(Array.isArray(this.data)){
                this.observeArray(this.data)
            }else {
                this.walk(this.data)
            }
        }
        observeArray(data){
            data.forEach(item=>{
                observe(item)
            })
        }
        walk(data){
            for (let key in data){
                defineProperty(data,key)
            }
        }
    }
    function defineProperty(data,key){
        let value = data[key]

        let dep = new Dep()

        observe(value)
        Object.defineProperty(data,key,{
            get(){
                if(target){
                    dep.add(target)
                }
                return value
            },
            set(v) {
                if( v === value) return
                value = v

                dep.notify()

            }
        })
    }
    class Dep{
        constructor() {
            this.sub = []
        }
        add(watcher){
            this.sub.push(watcher)
        }
        notify(){
            this.sub.forEach(item=>{
                item.update()
            })
        }
    }
    class Watcher{
        constructor(data,key) {
            this.data = data;
            this.key = key
            target = this

            this.get()

            target = null

        }
        get(){
            return this.data[this.key]
        }
        update(){
            console.log("更新")
        }
    }
    const vm = new Vue({
        data:{
            count :1
        }
    })
    new Watcher(vm,"count")
</script>
</body>
</html>